/*
 * @author Stanislovas Mickus
 * @version 1
 * @date 18 December, 2014
 *
 *  Copyright (C) 2013 Stanislovas Mickus
 *
 * Licensed under the GNU General Public License, Version 3 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.gnu.org/copyleft/gpl.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.stasmobstudios.musicplayer.fragments;

import android.database.Cursor;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TabHost;

import com.stasmobstudios.musicplayer.R;
import com.stasmobstudios.musicplayer.activities.MusicPlayerUI;
import com.stasmobstudios.musicplayer.adapters.MusicLibAdapter;
import com.stasmobstudios.musicplayer.contracts.LibraryDataMapping;
import com.stasmobstudios.musicplayer.contracts.MusicDataProviderContract;

public class LibraryFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {
    private static final String TAG = "LibraryFragment";
    private View libView;
    private MusicPlayerUI mMusicPlayerUI;
    public static int mCurrentArtistID = -1;
    public static int mCurrentAlbumID = -1;
    private static int LIB_TAB_SELECTED = -1;
    private MusicLibAdapter mTrackListAdapter;
    private MusicLibAdapter mAlbumListAdapter;
    private MusicLibAdapter mArtistListAdapter;

    public LibraryFragment() {
        super();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        this.mMusicPlayerUI = MusicPlayerUI.getMusicPlayerActivity();

        libView = inflater.inflate(R.layout.music_lib_view, container, false);

        TabHost libTabs = (TabHost) libView.findViewById(R.id.tabHost);
        libTabs.setup();
        TabHost.TabSpec spec = libTabs.newTabSpec("artists");
        spec.setIndicator("Artists");
        spec.setContent(R.id.artists);
        libTabs.addTab(spec);

        spec = libTabs.newTabSpec("albums");
        spec.setIndicator("Albums");
        spec.setContent(R.id.albums);
        libTabs.addTab(spec);

        spec = libTabs.newTabSpec("tracks");
        spec.setIndicator("Tracks");
        spec.setContent(R.id.track_list);
        libTabs.addTab(spec);

        return libView;
    }

    /**
     * Initialize library fragment view
     */
    public void initLibraryView() {
        // Attach library artist list adapter
        mArtistListAdapter = new MusicLibAdapter(
                mMusicPlayerUI,
                R.layout.lib_list_item,
                null,
                LibraryDataMapping.mArtistFromColumns,
                LibraryDataMapping.mArtistToFields,
                0
        );
        final ListView artist_list = (ListView) libView.findViewById(R.id.artists);
        artist_list.setAdapter(mArtistListAdapter);

        // Attach library album list adapter
        mAlbumListAdapter = new MusicLibAdapter(
                mMusicPlayerUI,
                R.layout.lib_list_item,
                null,
                LibraryDataMapping.mAlbumFromColumns,
                LibraryDataMapping.mAlbumToFields,
                0
        );
        final ListView albums_list = (ListView) libView.findViewById(R.id.albums);
        albums_list.setAdapter(mAlbumListAdapter);

        // Attach track list adapter
        mTrackListAdapter = new MusicLibAdapter(
                mMusicPlayerUI,
                R.layout.track_list_item,
                null,
                LibraryDataMapping.mTrackFromColumns,
                LibraryDataMapping.mTrackToFields,
                0
        );
        final ListView tracks_list = (ListView) libView.findViewById(R.id.track_list);
        tracks_list.setAdapter(mTrackListAdapter);


        // Library lists listeners
        artist_list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                // Update artist selection remembering scroll position
                int currentVisibleArtist = artist_list.getFirstVisiblePosition();
                View v = artist_list.getChildAt(0);
                int top = (v == null) ? 0 : v.getTop();
                mArtistListAdapter.setCurrentTrack(i);
                artist_list.setAdapter(mArtistListAdapter);
                artist_list.setSelectionFromTop(currentVisibleArtist, top);

                //Get current artistID
                Cursor artistCursor = mArtistListAdapter.getCursor();
                artistCursor.moveToPosition(i);
                // For new selected artist update album and track listviews
                int selectedArtistID = artistCursor.getInt(artistCursor.getColumnIndex(MusicDataProviderContract.ARTIST_ID));
                if (selectedArtistID != mCurrentArtistID) {
                    mMusicPlayerUI.getPlaybackSrevice().setCurrentTrackNo(-1);
                    mAlbumListAdapter.setCurrentTrack(-1);
                    mTrackListAdapter.setCurrentTrack(-1);
                    mCurrentArtistID = selectedArtistID;
                    mCurrentAlbumID = -1;
                    getLoaderManager().restartLoader(MUSIC_ALBUM_LOADER, null, LibraryFragment.this);
                    getLoaderManager().restartLoader(MUSIC_TRACK_LOADER, null, LibraryFragment.this);
                    LIB_TAB_SELECTED = 1;
                } else
                    ((TabHost) libView.findViewById(R.id.tabHost)).setCurrentTab(1);
            }
        });
        albums_list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                // Update album selection remembering scroll position
                int currentVisibleAlbum = albums_list.getFirstVisiblePosition();
                View v = albums_list.getChildAt(0);
                int top = (v == null) ? 0 : v.getTop();
                mAlbumListAdapter.setCurrentTrack(i);
                albums_list.setAdapter(mAlbumListAdapter);
                albums_list.setSelectionFromTop(currentVisibleAlbum, top);

                //Get current albumID
                Cursor albumCursor = mAlbumListAdapter.getCursor();
                albumCursor.moveToPosition(i);
                // For new selected album update track listviews
                int selctedAlbumID = albumCursor.getInt(albumCursor.getColumnIndex(MusicDataProviderContract.ALBUM_ID));
                if (selctedAlbumID != mCurrentAlbumID) {
                    mMusicPlayerUI.getPlaybackSrevice().setCurrentTrackNo(-1);
                    mTrackListAdapter.setCurrentTrack(-1);
                    mCurrentAlbumID = selctedAlbumID;
                    getLoaderManager().restartLoader(MUSIC_TRACK_LOADER, null, LibraryFragment.this);
                    LIB_TAB_SELECTED = 2;
                } else
                    ((TabHost) libView.findViewById(R.id.tabHost)).setCurrentTab(2);
            }
        });
        tracks_list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                // Update track selection remembering scroll position
                int currentVisibleItem = tracks_list.getFirstVisiblePosition();
                View v = tracks_list.getChildAt(0);
                int top = (v == null) ? 0 : v.getTop();
                mTrackListAdapter.setCurrentTrack(position);
                tracks_list.setAdapter(mTrackListAdapter);
                tracks_list.setSelectionFromTop(currentVisibleItem, top);

                try {
                    mMusicPlayerUI.updatePlayingSate(mMusicPlayerUI.getPlaybackSrevice().mediaPlay(position));
                } catch (Exception e) {
                    e.printStackTrace();
                    Log.e(TAG, "track_list::setOnItemClickListener(): FAILED to play selected track");
                }
            }
        });
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        // Initialize library view
        initLibraryView();
        // Initialize music library cursors
        getLoaderManager().initLoader(MUSIC_TRACK_LOADER, null, LibraryFragment.this);
        getLoaderManager().initLoader(MUSIC_ALBUM_LOADER, null, LibraryFragment.this);
        getLoaderManager().initLoader(MUSIC_ARTIST_LOADER, null, LibraryFragment.this);
    }

    /**
     **************************   Music library cursor handling methods   **************************
     */
    private static final int MUSIC_TRACK_LOADER = 0;
    private static final int MUSIC_ALBUM_LOADER = 1;
    private static final int MUSIC_ARTIST_LOADER = 2;
    /*
    * Callback that's invoked when the system has initialized the Loader and
    * is ready to start the query. This usually happens when initLoader() is
    * called. The loaderID argument contains the ID value passed to the
    * initLoader() call.
    */
    @Override
    public Loader<Cursor> onCreateLoader(int loaderID, Bundle bundle)
    {
    /*
     * Takes action based on the ID of the Loader that's being created
     */
        switch (loaderID) {
            case MUSIC_TRACK_LOADER:
                String[] selMusicArgs = { ((mCurrentAlbumID != -1) ? String.valueOf(mCurrentAlbumID) : "%"), ((mCurrentArtistID != -1) ? String.valueOf(mCurrentArtistID) : "%") };
                // Returns a new CursorLoader for track list
                return new CursorLoader(
                        mMusicPlayerUI,
                        MusicDataProviderContract.CONTENT_URI,
                        MusicDataProviderContract.PROJECTION_ALL_TRACKS,
                        MusicDataProviderContract.SELECTION_MUSIC,
                        selMusicArgs,
                        null
                );
            case MUSIC_ALBUM_LOADER:
                String[] selAlbumArgs = { ((mCurrentArtistID != -1) ? String.valueOf(mCurrentArtistID) : "%") };
                // Returns a new CursorLoader for album list
                return new CursorLoader(
                        mMusicPlayerUI,
                        MusicDataProviderContract.CONTENT_URI,
                        MusicDataProviderContract.PROJECTION_ALL_ALBUMS,
                        MusicDataProviderContract.SELECTION_MUSIC_ALBUMS,
                        selAlbumArgs,
                        null
                );
            case MUSIC_ARTIST_LOADER:
                // Returns a new CursorLoader for artist list
                return new CursorLoader(
                        mMusicPlayerUI,
                        MusicDataProviderContract.CONTENT_URI,
                        MusicDataProviderContract.PROJECTION_ALL_ARTIST,
                        MusicDataProviderContract.SELECTION_MUSIC_ARTISTS,
                        null,
                        null
                );
            default:
                // An invalid id was passed in
                return null;
        }
    }

    /**
     * Defines the callback that CursorLoader calls
     * when it's finished its query
     */
    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        switch (loader.getId()) {
            case MUSIC_TRACK_LOADER:
                mTrackListAdapter.changeCursor(cursor);
                // Update playback service track list when connected to service
                if (mMusicPlayerUI.getPlaybackSrevice() != null) {
                    setTracksList();
                    mMusicPlayerUI.notifyLibCursorLoadFinished();
                } else {
                    mMusicPlayerUI.setOnConectedToPlaybackServiceListener(new MusicPlayerUI.OnConnectedToPlaybackServiceListener() {
                        @Override
                        public void onConnected() {
                            setTracksList();
                            mMusicPlayerUI.notifyLibCursorLoadFinished();
                        }
                    });
                }
                break;
            case MUSIC_ALBUM_LOADER:
                mAlbumListAdapter.changeCursor(cursor);
                break;
            case MUSIC_ARTIST_LOADER:
                mArtistListAdapter.changeCursor(cursor);
                break;
            default:
                break;
        }

        if (LIB_TAB_SELECTED != -1)
            ((TabHost) libView.findViewById(R.id.tabHost)).setCurrentTab(LIB_TAB_SELECTED);
    }


    /**
     * Invoked when the CursorLoader is being reset. For example, this is
     * called if the data in the provider changes and the Cursor becomes stale.
     */
    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        switch (loader.getId()) {
            case MUSIC_TRACK_LOADER:
                mTrackListAdapter.changeCursor(null);
                break;
            case MUSIC_ALBUM_LOADER:
                mAlbumListAdapter.changeCursor(null);
                break;
            case MUSIC_ARTIST_LOADER:
                mArtistListAdapter.changeCursor(null);
                break;
            default:
                break;
        }
    }

    /**
     * Prepare track list information for playback service
     */
    protected void setTracksList() {
        if (mMusicPlayerUI.getPlaybackSrevice() != null && mTrackListAdapter.getCursor() != null) {
            Cursor tracksCursor = mTrackListAdapter.getCursor();

            String[] trackUriArray = new String[tracksCursor.getCount()];

            int i = 0;
            if (tracksCursor.moveToFirst())
                trackUriArray[i] = tracksCursor.getString(tracksCursor.getColumnIndex(MusicDataProviderContract.DATA));
            while ((tracksCursor.moveToNext())) {
                i++;
                trackUriArray[i] = tracksCursor.getString(tracksCursor.getColumnIndex(MusicDataProviderContract.DATA));
            }

            mMusicPlayerUI.getPlaybackSrevice().setTrackDataArray(trackUriArray);
        }
    }
}
